﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.IO;
using System.Runtime.InteropServices;

namespace JCFramework.AssisTest
{
    public class CodeTimer : IDisposable
    {
        private TextWriter m_writer;

        public TextWriter Writer
        {
            get
            {
                if (m_writer == null)
                {
                    m_writer = Console.Out;
                }
                return m_writer;
            }
            set
            {
                m_writer = value;
            }
        }

        public static void Initialize()
        {
            Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
            Thread.CurrentThread.Priority = ThreadPriority.Highest;
        }     

        private Stopwatch watch;

        private ulong cycleCount;

        public CodeTimer(string name)
        {
            watch = new Stopwatch();
            cycleCount = GetCycleCount();
            Writer.WriteLine(name);
            watch.Start();
        }

        public CodeTimer(string name, TextWriter writer)
            : this(name)
        {
            this.Writer = writer;
        }

        public static void Time(string name, int iteration, Action action)
        {
            using (CodeTimer timer = new CodeTimer(name))
            {
                for (int i = 0; i < iteration; i++) action();
            }
        }



        #region IDisposable Members

        public void Dispose()
        {
            watch.Stop();
            var cpuCycleCount = GetCycleCount() - cycleCount;
            Writer.WriteLine("\tTime Elapsed:\t" + watch.Elapsed.ToString());
            Writer.WriteLine("\tCPU Cycles:\t" + cpuCycleCount.ToString("N0"));
        }



        #endregion

        private ulong GetCycleCount()
        {
            ulong cycleCount = 0;
            //QueryThreadCycleTime(GetCurrentThread(), ref cycleCount);
            return cycleCount;
        }

        //[DllImport("kernel32.dll")]
        //[return: MarshalAs(UnmanagedType.Bool)]
        //static extern bool QueryThreadCycleTime(IntPtr threadHandle, ref ulong cycleTime);

        //[DllImport("kernel32.dll")]
        //static extern IntPtr GetCurrentThread();
    }
}
